package com.liu.spring.framework.beans.support;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;

/**
 * @author LIU
 * @version 1.0
 * @date 2024/5/18 15:59
 * @description TODO
 */
public class BeanDefinitionReader {
    // 保存用户的配置文件  application.yml
    private Properties contextConfig = new Properties();

    // 缓存从包路径下扫描的全类名，需要被注册的BeanClass们
    private List<String> registerBeanClasses = new ArrayList<>();


    public BeanDefinitionReader(String... locations) {
        // 1.加载properties配置文件
        doLoadConfig(locations[0]);
        // 2.扫描相关类
        doScanner(contextConfig.getProperty("scanPackage"));
    }

    //扫描ClassPath下符合包路径规则所有的Class文件
    private  void doScanner(String scanPackage) {
        String path = "/" + scanPackage.replaceAll("\\.", "/");
        URL resource = this.getClass().getClassLoader().getResource(path);
        File classPath = new File(resource.getFile());

        for (File file : classPath.listFiles()) {
            if (file.isDirectory()){
                doScanner(scanPackage + "." + file.getName());
            }else {
                if (file.getName().endsWith(".class")) continue;

                // 得到包名 com.liu.demo.UserService
                String className = scanPackage + "." + file.getName().replaceAll(".class", "");
                // 实例化，要用到  Class.forName(className);
                registerBeanClasses.add(className);
            }

        }
    }

    /**
     * 根据contextConfigLocation的路径去ClassPath下找到对应的配置文件
     *    getResourceAsStream() 是java中用于加载资源文件的方法之一。
     *    它是 ClassLoader 和 Class 类提供的方法，用于从类路径（ClassPath）中获取资源文件并返回一个输入流 （InputStream）。
     *    这个方法常用于加载配置文件，模板文件，图片，音频等各种类型的资源。
     *
    */
    private void doLoadConfig(String contextConfigLocation) {
        InputStream is = this.getClass().getClassLoader().getResourceAsStream(contextConfigLocation);
        try {
            contextConfig.load(is);
        } catch (IOException e) {
            e.printStackTrace();
        }finally {

            try {
                if (is!= null){
                    is.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

    }
}
